package roborally.program.command;

import java.util.List;

import roborally.itemsonboard.Robot;
import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Immutable;
import be.kuleuven.cs.som.annotate.Raw;

/**
 * A class representing a FlowCommand that has a condition that determines if the commands are executed.
 * Only if the condition evaluates to true, the internal commands are executed.
 * 
 * @invar (repeated)
 * 		The interal commands of this conditionalCommand must be valid.
 * 		| hasProperInteralCommands()
 * @invar The condition of this conditionalCommand must be valid.
 * 		| isValidCondition(this.getCondition())
 * 
 * @author Molderez Tom, 2de bach Ingenieurswetenschappen Computerwetenschappen-Elektrotechniek and Reniers Jorn, 2de bach Ingenieurswetenschappen Werktuigkunde-Computerwetenschappen
 * @version 1.0
 *
 */
public abstract class ConditionalCommand extends FlowCommand {
	
	/**
	 * Creates a new ConditionalCommand.
	 * 
	 * @param condition The condition of this conditionalCommand.
	 * @param commands The interal commands of this ConditionalCommand.
	 * @post The condition of this will be equal to the given condition.
	 * @post For every command in commands, according the order, this new will contain the specific command.
	 * @throws IllegalArgumentException
	 * 		When the commands are not valid according isValidInternalCommands.
	 * 		| !isValidInternalCommands(commands)
	 * @throws IllegalArgumentException
	 * 		When the condition is not valid, specified by isValidCondition.
	 * 		| !isValidCondition(condition)
	 */
	protected ConditionalCommand(Condition condition, List<? extends Command> commands) 
			throws IllegalArgumentException {
		super(commands);
		if(!isValidCondition(condition))
			throw new IllegalArgumentException("The given condition is not valid: " + condition.toString());
		this.condition = condition;
	}
	
	/**
	 * Returns the condition that determines if the internal commands are executed.
	 */
	@Basic @Immutable @Raw
	public Condition getCondition(){
		return condition;
	}
	
	/**
	 * Controls if the condition is valid of this conditionalCommand.
	 * 
	 * @param condition The condition to be controlled.
	 * @return False if the condition is null.
	 * 		| if condition == null
	 * 		|	then result == false
	 */
	@Raw
	public static boolean isValidCondition(Condition condition) {
		return condition != null;
	}

	/**
	 * The condition of this conditionalCommand.
	 */
	private final Condition condition;
	
	/**
	 * Executes the internal commands only if the return value of the condition is true
	 * after executing the condition.
	 * 
	 * @effect Executes the condition. If the return value of the condition is true,
	 * only then the internal commands of this are also executed.
	 * @throws IllegalArgumentException
	 * 		When the given robot is not valid according the condition or the internal
	 * 		commands.
	 */
	@Override
	public void execute(Robot robot) throws IllegalArgumentException {
		getCondition().execute(robot);
		if(getCondition().getReturnValue())
			super.execute(robot);
	}
}
